import { pick } from "lodash-es";

/**
 * 拆分传入组件的入参为style和组件的自身参数
 */
export const componentParam = (props: { [key: string]: any }, pickArr: string[]) => {
    const styleProps = pick(props, pickArr);
    const componentProps = {};
    Object.keys(props).forEach(key => {
        if(!pickArr.includes(key)){
            Reflect.set(componentProps, key, props[key]);
        }
    })
    return {
        styleProps,
        componentProps
    }
}

/**
 * 转换编辑部分到实际网页之间的宽高值
 */
const effectKeys = [{
    key: "width",
    proportion: "widthProportion",
    afterTransform: (value: number) => `${value}px`
}, {
    key: "height",
    proportion: "heightProportion",
    afterTransform: (value: number) => `${value}px`
}, {
    key: "lineHeight",
    proportion: "heightProportion"
}, {
    key: "top",
    proportion: "heightProportion",
    afterTransform: (value: number) => `${value}px`
}, {
    key: "left",
    proportion: "widthProportion",
    afterTransform: (value: number) => `${value}px`
}];
export const transformStyle = (containerWidth: number, containerHeight: number, styleProps: {[key: string]: any}, pageStyle: {[key: string]: any}) => {
    // 取得当前页面的宽度
    const currentWidth = containerWidth || document.body.clientWidth;
    const currentHeight = containerHeight || document.body.clientHeight;
    const { height, width } = pageStyle || {};
    Reflect.set(styleProps, "position", "absolute")
    if(!(height && width)) return styleProps;
    const editHieght = String(height).includes("px") ? parseInt(String(height).slice(0, -2)) : parseInt(height);
    const editWidth = String(width).includes("px") ? parseInt(String(width).slice(0, -2)) : parseInt(width);
    if(Number.isNaN(editHieght) || Number.isNaN(editWidth)) return styleProps;
    const proportionMap: {[key: string]: number} = {
        widthProportion: currentWidth / editWidth,
        heightProportion: currentHeight / editHieght
    }
    effectKeys.forEach(eff => {
        if(Reflect.has(styleProps, eff.key)){
            const strVlaue = Reflect.get(styleProps, eff.key);
            const curValue = String(strVlaue).includes("px") ? parseInt(String(strVlaue).slice(0, -2)) : parseInt(strVlaue);
            if(!Number.isNaN(curValue)){
                const trulyValue = proportionMap?.[eff.proportion] * curValue;
                Reflect.set(styleProps, eff.key, eff.afterTransform ? eff.afterTransform(trulyValue) : trulyValue);
            }
        }
    })
    return styleProps;
}

class JSONUtil {
    n = "\n";
    t = "\t";
    __writeObj(obj: any, level: number, isInArray?: boolean): string {
        if (obj === null) {
            return "null";
        }
        if (obj.constructor === Number || obj.constructor === Date || obj.constructor === String || obj.constructor === Boolean) {
            let v = obj.toString();
            let tab = isInArray ? this.__repeatStr(this.t, level - 1) : "";
            if (obj.constructor === String || obj.constructor === Date) {
                return tab + ("\"" + v + "\"");
            }
            else if (obj.constructor === Boolean) {
                return tab + v.toLowerCase();
            }
            else {
                return tab + (v);
            }
        }
        let currentObjStrings = [];
        for (let name in obj) {
            let temp = [];
            let paddingTab = this.__repeatStr(this.t, level);
            temp.push(paddingTab);
            temp.push(name + ": ");
            let val = obj[name];
            if (val === null) {
                temp.push("null");
            } else {
                let c = val.constructor;
                if (c === Array) {
                    temp.push("[" + this.n);
                    var levelUp = level + 2;
                    var tempArrValue = [];
                    for (var i = 0; i < val.length; i++) {                     
                        tempArrValue.push(this.__writeObj(val[i], levelUp, true));
                    }
                    temp.push(tempArrValue.join("," + this.n));
                    temp.push(this.n + paddingTab + "]");
                } else if (c instanceof Function) {
                    temp.push(val.toString());
                } else {
                    temp.push(this.__writeObj(val, level + 1));
                }
            }
            currentObjStrings.push(temp.join(""));
        }
        return (level > 1 && !isInArray ? this.n : "")
            + this.__repeatStr(this.t, level - 1) + "{" + this.n
            + currentObjStrings.join("," + this.n)
            + this.n + this.__repeatStr(this.t, level - 1) + "}";
    }
    __repeatStr(str: string, times: number) {
        var newStr = [];
        if (times > 0) {
            for (var i = 0; i < times; i++) {
                newStr.push(str);
            }
        }
        return newStr.join("");
    }
    /**
     * 格式化输入JSON字符串
     * @param obj 
     * @returns 
     */
    convertToString(obj: any) {
        if(!obj) return undefined;
        return this.__writeObj(obj, 1);
    }
}

export const jsonUtils = new JSONUtil();